package myLearnjdk.jdk.lang.iot;

/**
 * 自定义字节数组对象 ByteDataBuffer
 * @Description: 前置报文封装的对象
 * @author  yangcheng
 * @date:   2018年12月3日
 */
public class ByteDataBuffer {
	
	private static int INCREASE_DATA_SIZE = 256;
	private boolean inBigEndian = true;
	private byte[] dataBuffer;
	private int pos = 0;
	private int bitOperPos = -1; //默认为-1   
	private int dataSize;
	private String encoding = "UTF-8";
	private char defaultFillChar;//默认的补足指定长度的字符

	public ByteDataBuffer() {
		this(INCREASE_DATA_SIZE);
	}

	public ByteDataBuffer(int size) {
		this.dataBuffer = new byte[size];
		this.dataSize = 0;
	}

	public ByteDataBuffer(byte[] data) {
		if (data != null) {
			this.dataBuffer = data;
			this.dataSize = data.length;
		} else {
			this.dataBuffer = new byte[INCREASE_DATA_SIZE];
			this.dataSize = 0;
		}
	}
	/**
	 * 确保byte数组长度够用
	 * @param minCapacity  需要的最小数组长度
	 * @throws Exception
	 */
	public void ensureCapacity(int minCapacity) throws Exception {
		if (this.dataBuffer.length < minCapacity) {
			int nextBufSize = INCREASE_DATA_SIZE
					* (minCapacity / INCREASE_DATA_SIZE + 1);
			byte[] data = new byte[nextBufSize];
			System.arraycopy(this.dataBuffer, 0, data, 0,
					this.dataBuffer.length);
			this.dataBuffer = data;
		}
	}

	public void writeBytes(byte[] data) throws Exception {
		writeBytes(data, 0, data.length);
	}

	private byte[] reverse(byte[] bytes) {
		if ((bytes != null) && (bytes.length > 1)) {
			int swapCount = bytes.length / 2;
			int endPos = bytes.length - 1;
			for (int i = 0; i < swapCount; i++) {
				byte b = bytes[i];
				bytes[i] = bytes[(endPos - i)];
				bytes[(endPos - i)] = b;
			}
		}
		return bytes;
	}

	/**
	 * 将字符原样封装到报文中，两个字符占一个字节，报文字节数=(s.length())/2  -----该方法要求字符串s必须是偶数位
	 * @param s
	 * @return
	 * @throws Exception
	 */
	public void writeBCDString(String s) throws Exception {
		byte[] data = StringUtils.decodeHex(s);
		if (!this.inBigEndian) {
			reverse(data);
		}
		writeBytes(data);
	}
	/**
	 * 写入字节数组到buffer
	 * @param data  需要写入的数据
	 * @param srcPos 需要写入数据的原数组起始位置
	 * @param length 需要写入原数组的长度
	 * @throws Exception
	 */
	public void writeBytes(byte[] data, int srcPos, int length)
			throws Exception {
		if ((data == null) || (length <= 0)) {
			return;
		}
		if (srcPos + length > data.length) {
			length = data.length - srcPos;
		}
		ensureCapacity(this.pos + length);
		System.arraycopy(data, srcPos, this.dataBuffer, this.pos, length);
		this.pos += length;
	}
	/**
	 * 向buffer中添加相同的“字节数据”
	 * @param data  需要写入的字节数据
	 * @param length 需要写入多少位
	 * @throws Exception
	 */
	public void writeFillerBytes(byte data, int length) throws Exception {
		ensureCapacity(this.pos + length);
		for (int j = 0; j < length; j++) {
			this.dataBuffer[this.pos] = data;
			this.pos += 1;
		}
	}
	/**
	 * 1byte
	 * @param data
	 * @throws Exception
	 */
	public void writeInt8(byte data) throws Exception {
		ensureCapacity(this.pos + 1);
		this.dataBuffer[this.pos] = data;
		this.pos += 1;
	}
	/**
	 * 2byte
	 * @param i
	 * @throws Exception
	 */
	public void writeInt16(int i) throws Exception {
		ensureCapacity(this.pos + 2);
		if (this.inBigEndian) {
			this.dataBuffer[this.pos] = (byte) (i >>> 8 & 0xFF);
			this.dataBuffer[(this.pos + 1)] = (byte) (i & 0xFF);
		} else {
			this.dataBuffer[this.pos] = (byte) (i & 0xFF);
			this.dataBuffer[(this.pos + 1)] = (byte) (i >>> 8 & 0xFF);
		}
		this.pos += 2;
	}
	/**
	 * 4byte
	 * @param i
	 * @throws Exception
	 */
	public void writeInt32(int i) throws Exception {
		ensureCapacity(this.pos + 4);
		if (this.inBigEndian) {
			this.dataBuffer[this.pos] = (byte) (i >>> 24 & 0xFF);
			this.dataBuffer[(this.pos + 1)] = (byte) (i >>> 16 & 0xFF);
			this.dataBuffer[(this.pos + 2)] = (byte) (i >>> 8 & 0xFF);
			this.dataBuffer[(this.pos + 3)] = (byte) (i & 0xFF);
		} else {
			this.dataBuffer[this.pos] = (byte) (i & 0xFF);
			this.dataBuffer[(this.pos + 1)] = (byte) (i >>> 8 & 0xFF);
			this.dataBuffer[(this.pos + 2)] = (byte) (i >>> 16 & 0xFF);
			this.dataBuffer[(this.pos + 3)] = (byte) (i >>> 24 & 0xFF);
		}
		this.pos += 4;
	}
	/**
	 * 8byte
	 * @param l
	 * @throws Exception
	 */
	public void writeInt64(long l) throws Exception {
		ensureCapacity(this.pos + 8);
		if (this.inBigEndian) {
			this.dataBuffer[this.pos] = (byte) (int) (l >>> 56 & 0xFF);
			this.dataBuffer[(this.pos + 1)] = (byte) (int) (l >>> 48 & 0xFF);
			this.dataBuffer[(this.pos + 2)] = (byte) (int) (l >>> 40 & 0xFF);
			this.dataBuffer[(this.pos + 3)] = (byte) (int) (l >>> 32 & 0xFF);
			this.dataBuffer[(this.pos + 4)] = (byte) (int) (l >>> 24 & 0xFF);
			this.dataBuffer[(this.pos + 5)] = (byte) (int) (l >>> 16 & 0xFF);
			this.dataBuffer[(this.pos + 6)] = (byte) (int) (l >>> 8 & 0xFF);
			this.dataBuffer[(this.pos + 7)] = (byte) (int) (l & 0xFF);
		} else {
			this.dataBuffer[this.pos] = (byte) (int) (l & 0xFF);
			this.dataBuffer[(this.pos + 1)] = (byte) (int) (l >>> 8 & 0xFF);
			this.dataBuffer[(this.pos + 2)] = (byte) (int) (l >>> 16 & 0xFF);
			this.dataBuffer[(this.pos + 3)] = (byte) (int) (l >>> 24 & 0xFF);
			this.dataBuffer[(this.pos + 4)] = (byte) (int) (l >>> 32 & 0xFF);
			this.dataBuffer[(this.pos + 5)] = (byte) (int) (l >>> 40 & 0xFF);
			this.dataBuffer[(this.pos + 6)] = (byte) (int) (l >>> 48 & 0xFF);
			this.dataBuffer[(this.pos + 7)] = (byte) (int) (l >>> 56 & 0xFF);
		}
		this.pos += 8;
	}

	public void writeFloat(float f) throws Exception {
		writeInt32(Float.floatToIntBits(f));
	}

	public void writeDouble(double d) throws Exception {
		writeInt64(Double.doubleToLongBits(d));
	}

	public void writeUCS2Char(char c) throws Exception {
		writeInt16(c);
	}
	/**
	 * 写UTF-8文本
	 * 长度域为2个字节--写到报文中的数据是字符对应的ASCII编码值（数字看起来是+30开始的，因为0的ASCII码值为30）
	 * @param s
	 * @throws Exception
	 */
	public void writeString(String s) throws Exception {
		if (s == null) {
			writeInt16(-1);
			return;
		}
		byte[] data = s.getBytes(this.encoding);
		writeInt16(data.length);
		writeBytes(data, 0, data.length);
	}
	/**
	 * 写UTF-8文本
	 * 写到报文中的数据是字符对应的ASCII编码值
	 * @param s
	 * @throws Exception
	 */
	public void writeStringWith0neByteLen(String s) throws Exception {
		if (s == null) {
			writeInt16(-1);
			return;
		}
		byte[] data = s.getBytes(this.encoding);
		writeInt8((byte)data.length);
		writeBytes(data, 0, data.length);
	}
	/**
	 * 与writeStringWith0neByteLen是同一个方法，ASCII字符串--制定了编码是的字符集（默认为UTF-8）
	 * @param s
	 * @throws Exception
	 */
	public void writeAnsiString(String s) throws Exception {
		if (s == null) {
			writeInt16(-1);
			return;
		}
		byte[] data = s.getBytes(this.encoding);
		writeInt8(Integer.valueOf(data.length).byteValue());
		writeBytes(data, 0, data.length);
	}
	/**
	 * 写入自定长度的字符串
	 * @param s
	 * @param size
	 * @throws Exception
	 */
	public void writeString(String s, int size) throws Exception {
		writeString(s, size, this.defaultFillChar);
	}
	/**
	 * 写入指定的字符串并指定占用字节数组的长度
	 * @param s 写入的字符串
	 * @param size  指定写入buffer的长度---为String数据对应的byte[]数组的长度
	 * @param fillChar  当写入长度大于字符串对应byte[]长度时，填充空位的字符
	 * @throws Exception
	 */
	public void writeString(String s, int size, char fillChar) throws Exception {
		if (s == null) {
			s = "";
		}
		byte[] data = s.getBytes(this.encoding);
		if (data.length >= size) {
			writeBytes(data, 0, size);
		} else {
			writeBytes(data, 0, data.length);
			/**
			 * 将指定长度的空位用指定的字符填充
			 */
			writeFillerBytes((byte) (fillChar & 0xFF), size - data.length);
		}
	}

	public int readBytes(byte[] data) throws Exception {
		return readBytes(data, 0, data.length);
	}
	/**
	 * 从buffer中读取一份指定长度的byte[]
	 * @param data  封装读取出的数据的byte[]
	 * @param destPos 从data的destPos下标开始转载读取出的数据
	 * @param length  读取数据的长度
	 * @return
	 * @throws Exception
	 */
	public int readBytes(byte[] data, int destPos, int length) throws Exception {
		if (length > this.dataBuffer.length - this.pos) {
			length = this.dataBuffer.length - this.pos;
		}
		if (length > 0) {
			System.arraycopy(this.dataBuffer, this.pos, data, destPos, length);
		}
		this.pos += length;
		return length;
	}

	public short readInt16() throws Exception {
		short word0;
		if (this.inBigEndian)
			word0 = (short) (((this.dataBuffer[this.pos] & 0xFF) << 8) + (this.dataBuffer[(this.pos + 1)] & 0xFF));
		else {
			word0 = (short) ((this.dataBuffer[this.pos] & 0xFF) + ((this.dataBuffer[(this.pos + 1)] & 0xFF) << 8));
		}
		this.pos += 2;
		return word0;
	}

	public int readInt32() throws Exception {
		int i;
		if (this.inBigEndian)
			i = ((this.dataBuffer[this.pos] & 0xFF) << 24)
					+ ((this.dataBuffer[(this.pos + 1)] & 0xFF) << 16)
					+ ((this.dataBuffer[(this.pos + 2)] & 0xFF) << 8)
					+ (this.dataBuffer[(this.pos + 3)] & 0xFF);
		else {
			i = (this.dataBuffer[this.pos] & 0xFF)
					+ ((this.dataBuffer[(this.pos + 1)] & 0xFF) << 8)
					+ ((this.dataBuffer[(this.pos + 2)] & 0xFF) << 16)
					+ ((this.dataBuffer[(this.pos + 3)] & 0xFF) << 24);
		}
		this.pos += 4;
		return i;
	}
	
	
	public long readInt64() throws Exception {
		long l = 0;
		if (this.inBigEndian){
			/**
			 * 原方法存在进度丢失  (this.dataBuffer[this.pos] & 0xFF) << 56执行时  由于左侧计算出来为int类型  导致左移56位之后数据丢失
			 * 因此先改为  (long)(this.dataBuffer[this.pos] & 0xFF) << 56 的形式  即首先将作测数据转成long类型然后左移  这样不会丢失精度
			 */
			l += ((long)(this.dataBuffer[this.pos] & 0xFF) << 56);
			l += ((long)(this.dataBuffer[(this.pos + 1)] & 0xFF) << 48);
			l += ((long)(this.dataBuffer[(this.pos + 2)] & 0xFF) << 40);
			l += ((long)(this.dataBuffer[(this.pos + 3)] & 0xFF) << 32);
			l += ((long)(this.dataBuffer[(this.pos + 4)] & 0xFF) << 24);
			l += ((long)(this.dataBuffer[(this.pos + 5)] & 0xFF) << 16);
			l += ((long)(this.dataBuffer[(this.pos + 6)] & 0xFF) << 8);
			l += ((long)this.dataBuffer[(this.pos + 7)] & 0xFF);
		}else {
			l = ((long)this.dataBuffer[this.pos] & 0xFF)
					+ ((long)(this.dataBuffer[(this.pos + 1)] & 0xFF) << 8)
					+ ((long)(this.dataBuffer[(this.pos + 2)] & 0xFF) << 16)
					+ ((long)(this.dataBuffer[(this.pos + 3)] & 0xFF) << 24)
					+ ((long)(this.dataBuffer[(this.pos + 4)] & 0xFF) << 32)
					+ ((long)(this.dataBuffer[(this.pos + 5)] & 0xFF) << 40)
					+ ((long)(this.dataBuffer[(this.pos + 6)] & 0xFF) << 48)
					+ ((long)(this.dataBuffer[(this.pos + 7)] & 0xFF) << 56);
		}
		this.pos += 8;
		return l;
	}	/**
	 * 读取完数据之后 需要将指针还原
	 * @param bitSize
	 * @return
	 * @throws Exception
	 */
	private int tmpReadInteger(int bitSize) throws Exception {
		int tempPos = this.pos;
		int result = 0;
		switch (bitSize) {
		case 8:
			result = readInt8();
			break;
		case 16:
			result = readInt16();
			break;
		case 32:
			result = readInt32();
		}

		this.pos = tempPos;
		return result;
	}
	/**
	 * 向指定字节中写入0值（bit位写数据时先执行该方法占位）---写完之后 指针需要还原
	 * @param data
	 * @param bitSize
	 * @return
	 * @throws Exception
	 */
	private int tmpWriteInteger(int data, int bitSize) throws Exception {
		int tempPos = this.pos;
		int result = 0;
		switch (bitSize) {
		case 8:
			writeInt8((byte) data);
			break;
		case 16:
			writeInt16((short) data);
			break;
		case 32:
			writeInt32(data);
		}

		this.pos = tempPos;
		return result;
	}
	/**
	 * 读取bit位数据，如果读取的是一个字节的一部分，则buffer读指针不变，知道将一个字节所有bit都读完，指针pos才变
	 * @param bitBlockSize  读取的比特位长度
	 * @return
	 * @throws Exception
	 */
	public boolean readBit(int bitBlockSize) throws Exception {
		if (this.bitOperPos < 0) {
			this.bitOperPos = (bitBlockSize - 1);
		}
		/**
		 * 先读取一个字节的数据
		 */
		int result = tmpReadInteger(bitBlockSize);
		boolean b = BitUtil.readBit(result, this.bitOperPos);
		this.bitOperPos -= 1;
		if (this.bitOperPos < 0) {
			this.pos += bitBlockSize / 8;
		}
		return b;
	}

	public void writeBit(boolean b, int bitBlockSize) throws Exception {
		if (this.bitOperPos < 0) {
			this.bitOperPos = (bitBlockSize - 1);//bit指针赋新值（bitBlockSize-1，即当操作位长度为8时，bitOperPos初始值为7）
			tmpWriteInteger(0, bitBlockSize);
		}
		int result = tmpReadInteger(bitBlockSize);
		if (b)
			result = BitUtil.setBit(result, this.bitOperPos);
		else {
			result = BitUtil.clearBit(result, this.bitOperPos);
		}
		tmpWriteInteger(result, bitBlockSize);
		this.bitOperPos -= 1;
		if (this.bitOperPos < 0)
			this.pos += bitBlockSize / 8;
	}

	public int readBit(int size, int bitBlockSize) throws Exception {
		if (this.bitOperPos < 0) {
			this.bitOperPos = (bitBlockSize - 1);
		}
		int result = tmpReadInteger(bitBlockSize);
		int n = BitUtil.readBit(result, this.bitOperPos - size + 1, size);
		this.bitOperPos -= size;

		if (this.bitOperPos < 0) {
			this.pos += bitBlockSize / 8;
		}
		return n;
	}
	/**
	 * 注意：自左向右填充数据
	 * @param n  设置的每一位上的值
	 * @param size 设置的位数
	 * @param bitBlockSize  bit的位数
	 * @throws Exception
	 */
	public void writeBit(int n, int size, int bitBlockSize) throws Exception {
		if (this.bitOperPos < 0) {
			this.bitOperPos = (bitBlockSize - 1);
			tmpWriteInteger(0, bitBlockSize);
		}
		int result = tmpReadInteger(bitBlockSize);
		result = BitUtil.write(result, this.bitOperPos - size + 1, size, n);
		this.bitOperPos -= size;
		tmpWriteInteger(result, bitBlockSize);
		if (this.bitOperPos < 0)
			this.pos += bitBlockSize / 8;
	}

	public void writeVarString(String s) throws Exception {
		if (s == null) {
			writeVarInt(-1);
			return;
		}
		byte[] data = s.getBytes(this.encoding);
		writeVarInt(data.length);
		writeBytes(data, 0, data.length);
	}

	public String readVarString() throws Exception {
		String result = null;
		int strLen = readVarInt();
		if (strLen > 0) {
			result = new String(this.dataBuffer, this.pos, strLen,
					this.encoding);
			this.pos += strLen;
		}
		if (strLen == 0) {
			return "";
		}
		return result;
	}

	public long readVarLong() throws Exception {
		byte[] buffer = this.dataBuffer;

		int b = buffer[(this.pos++)];
		long result = b & 0x7F;
		if ((b & 0x80) != 0) {
			b = buffer[(this.pos++)];
			result |= (b & 0x7F) << 7;
			if ((b & 0x80) != 0) {
				b = buffer[(this.pos++)];
				result |= (b & 0x7F) << 14;
				if ((b & 0x80) != 0) {
					b = buffer[(this.pos++)];
					result |= (b & 0x7F) << 21;
					if ((b & 0x80) != 0) {
						b = buffer[(this.pos++)];
						result |= (b & 0x7F) << 28;
						if ((b & 0x80) != 0) {
							b = buffer[(this.pos++)];
							result |= (b & 0x7F) << 35;
							if ((b & 0x80) != 0) {
								b = buffer[(this.pos++)];
								result |= (b & 0x7F) << 42;
								if ((b & 0x80) != 0) {
									b = buffer[(this.pos++)];
									result |= (b & 0x7F) << 49;
									if ((b & 0x80) != 0) {
										b = buffer[(this.pos++)];
										result |= b << 56;
									}
								}
							}
						}
					}
				}
			}
		}
		return result;
	}

	public void writeVarLong(long value) throws Exception {
		ensureCapacity(this.pos + 9);
		byte[] buffer = this.dataBuffer;
		if ((0xFFFFFF80 & value) == 0L) {// value <= 127时满足
			buffer[(this.pos++)] = (byte) (int) value;
			return;
		}
		if ((0xFFFFC000 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7);
			return;
		}
		if ((0xFFE00000 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 14);
			return;
		}
		if ((0xF0000000 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 14 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 21);
			return;
		}
		if ((0x0 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 14 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 21 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 28);
			return;
		}
		if ((0x0 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 14 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 21 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 28 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 35);
			return;
		}
		if ((0x0 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 14 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 21 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 28 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 35 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 42);
			return;
		}
		if ((0x0 & value) == 0L) {
			buffer[(this.pos++)] = (byte) (int) (value & 0x7F | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 14 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 21 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 28 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 35 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 42 | 0x80);
			buffer[(this.pos++)] = (byte) (int) (value >>> 49);
			return;
		}
		buffer[(this.pos++)] = (byte) (int) (value | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 7 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 14 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 21 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 28 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 35 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 42 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 49 | 0x80);
		buffer[(this.pos++)] = (byte) (int) (value >>> 56 & 0x7F);
	}

	public void writeVarInt(int value) throws Exception {
		ensureCapacity(this.pos + 5);
		byte[] buffer = this.dataBuffer;
		if ((0xFFFFFF80 & value) == 0) {
			buffer[(this.pos++)] = (byte) value;
			return;
		}
		if ((0xFFFFC000 & value) == 0) {
			buffer[(this.pos++)] = (byte) (value | 0x80);
			buffer[(this.pos++)] = (byte) (value >>> 7);
			return;
		}
		if ((0xFFE00000 & value) == 0) {
			buffer[(this.pos++)] = (byte) (value | 0x80);
			buffer[(this.pos++)] = (byte) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (value >>> 14);
			return;
		}
		if ((0xF0000000 & value) == 0) {
			buffer[(this.pos++)] = (byte) (value | 0x80);
			buffer[(this.pos++)] = (byte) (value >>> 7 | 0x80);
			buffer[(this.pos++)] = (byte) (value >>> 14 | 0x80);
			buffer[(this.pos++)] = (byte) (value >>> 21);
			return;
		}

		buffer[(this.pos++)] = (byte) (value | 0x80);
		buffer[(this.pos++)] = (byte) (value >>> 7 | 0x80);
		buffer[(this.pos++)] = (byte) (value >>> 14 | 0x80);
		buffer[(this.pos++)] = (byte) (value >>> 21 | 0x80);
		buffer[(this.pos++)] = (byte) (value >>> 28 & 0x7F);
	}

	public int readVarInt() {
		byte[] buffer = this.dataBuffer;
		int b = buffer[(this.pos++)];
		int result = b & 0x7F;
		if ((b & 0x80) != 0) {
			b = buffer[(this.pos++)];
			result |= (b & 0x7F) << 7;
			if ((b & 0x80) != 0) {
				b = buffer[(this.pos++)];
				result |= (b & 0x7F) << 14;
				if ((b & 0x80) != 0) {
					b = buffer[(this.pos++)];
					result |= (b & 0x7F) << 21;
					if ((b & 0x80) != 0) {
						b = buffer[(this.pos++)];
						result |= (b & 0x7F) << 28;
					}
				}
			}
		}
		return result;
	}

	public byte readInt8() throws Exception {
		if (this.dataBuffer.length - this.pos > 0) {
			byte result = this.dataBuffer[this.pos];
			this.pos += 1;
			return result;
		}
		throw new Exception("no Data");
	}

	public float readFloat() throws Exception {
		return Float.intBitsToFloat(readInt32());
	}

	public double readDouble() throws Exception {
		return Double.longBitsToDouble(readInt64());
	}

	public char readUCS2Char() throws Exception {
		return (char) readInt16();
	}

	public byte[] getBytes() {
		byte[] data = new byte[getDataSize()];
		System.arraycopy(this.dataBuffer, 0, data, 0, data.length);
		return data;
	}

/**
	 * 以String的形式读取指定长度的字节，-----直接通过byte[]与String的相互转化
	 * @param size
	 * @param fillByte  用于排除写入时自动填入的字符
	 * @return  返回读取到的String数据
	 * @throws Exception
	 */
	public String readString() throws Exception {
		String result = null;
		int strLen = readInt16();
		if (strLen > 0) {
			result = new String(this.dataBuffer, this.pos, strLen,
					this.encoding);
			this.pos += strLen;
		}
		if (strLen == 0) {
			return "";
		}
		return result;
	}
	
	public String readBCDString(int length) throws Exception {
		byte[] data = new byte[length / 2];
		readBytes(data);
		if (!this.inBigEndian) {
			reverse(data);
		}
		return StringUtils.encodeHex(data);
	}

	public String readString(int size) throws Exception {
		return readString(size, this.defaultFillChar);
	}
	/**
	 * 以指定字符集读取
	 * @param size
	 * @param fillByte
	 * @return
	 * @throws Exception
	 */
	public String readString(int size, char fillByte) throws Exception {
		int strLen = size;
		if (strLen > 0) {
			while ((strLen > 0)&& (this.dataBuffer[(this.pos + strLen - 1)] == fillByte)) {
				strLen--;
			}
			String result = new String(this.dataBuffer, this.pos, strLen,this.encoding);
			this.pos += size;
			return result;
		}

		return null;
	}
	
	public String readCString() throws Exception {
		byte[] data = getDataBuffer();
		int endPos = -1;
		for (int i = this.pos; i < data.length; i++)
			if (data[i] == 0) {
				endPos = i;
				break;
			}
		if (endPos < 0)
			endPos = data.length;
		String s = new String(data, this.pos, endPos - this.pos, this.encoding);
		this.pos = (endPos + 1);
		return s;
	}

	public void writeCString(String cs) throws Exception {
		if (cs == null)
			cs = "";
		byte[] data = cs.getBytes(this.encoding);
		int pos = -1;
		for (int i = 0; i < data.length; i++) {
			if (data[i] == 0) {
				pos = i;
				break;
			}
		}
		if (pos >= 0) {
			writeBytes(data, 0, pos + 1);
		} else {
			writeBytes(data, 0, data.length);
			writeInt8((byte) 0);
		}
	}

	public int getDataSize() {
		if (this.pos > this.dataSize) {
			this.dataSize = this.pos;
		}
		return this.dataSize;
	}

	public char getDefaultFillChar() {
		return this.defaultFillChar;
	}

	public String getEncoding() {
		return this.encoding;
	}

	public boolean isInBigEndian() {
		return this.inBigEndian;
	}

	public int getPos() {
		return this.pos;
	}

	public void setDefaultFillChar(char defaultFillChar) {
		this.defaultFillChar = defaultFillChar;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public void setInBigEndian(boolean inBigEndian) {
		this.inBigEndian = inBigEndian;
	}

	public void setPos(int pos) {
		this.pos = pos;
	}

	public byte[] getDataBuffer() {
		return this.dataBuffer;
	}

	public void reset() {
		this.dataSize = 0;
		this.pos = 0;
	}

	public boolean hasData() {
		return this.pos < this.dataSize;
	}

}
